//////////////////////////////////////////////////////////////////////////
#include "CompositeObject.h"
#include <cassert>
#include <cmath>
//////////////////////////////////////////////////////////////////////////
CompositeObject::CompositeObject()
: m_x(0)
, m_y(0)
, m_angle(0)
, m_name(L"")
, m_parent(NULL)
, m_visible(true)
{
	updateTransformationMatrix();
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::update(float dt)
{
	for(std::list<CompositeObject*>::iterator it = m_children.begin(); it != m_children.end(); ++it)
	{
		(*it)->update(dt);
	}
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::render()
{
	for(std::list<CompositeObject*>::iterator it = m_children.begin(); it != m_children.end(); ++it)
	{
		(*it)->render();
	}
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::updateTransformationMatrix()
{
	float cos_ = std::cos(m_angle);
	float sin_ = std::sin(m_angle);
	
	m_transformationMatrix.m[0][0] = cos_;
	m_transformationMatrix.m[0][1] = sin_;
	m_transformationMatrix.m[0][2] = 0.0f;
	m_transformationMatrix.m[1][0] = -sin_;
	m_transformationMatrix.m[1][1] = cos_;
	m_transformationMatrix.m[1][2] = 0.0f;
	m_transformationMatrix.m[2][0] = m_x;
	m_transformationMatrix.m[2][1] = m_y;
	m_transformationMatrix.m[2][2] = 1.0f;

	if(m_parent)
	{
		multiplyTransformationMatrix(m_parent->getTransformationMatrix());
	}
	
	for(std::list<CompositeObject*>::iterator it = m_children.begin(); it != m_children.end(); ++it)
	{
		(*it)->updateTransformationMatrix();
	}
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::setX( const float x )
{
	m_x = x;
	updateTransformationMatrix();
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::setY( const float y )
{
	m_y = y;
	updateTransformationMatrix();
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::setAngle( const float angle )
{
	m_angle = angle;
	updateTransformationMatrix();
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::addChild( CompositeObject* child )
{
	for(std::list<CompositeObject*>::iterator it = m_children.begin(); it != m_children.end(); ++it)
	{
		if( (*it) == child )
		{
			removeChild(child);
			break;
		}
	}

	m_children.push_back(child);
	if(child->getName() != L"")
	{
		assert(m_namedChildren.find(child->getName()) == m_namedChildren.end());
		m_namedChildren[child->getName()] = child;
	}
	child->setParent(this);
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::removeChild( CompositeObject* child )
{
	for(std::list<CompositeObject*>::iterator it = m_children.begin(); it != m_children.end(); ++it)
	{
		if( (*it) == child )
		{
			m_children.erase(it);
			if(child->getName() != L"")
			{
				m_namedChildren.erase(child->getName());
			}
			return;
		}
	}

	assert(0); //wrong child
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::setParent( CompositeObject* parent )
{
	if(m_parent)
	{
		m_parent->removeChild(this);
		m_parent = NULL;
	}

	m_parent = parent;
	updateTransformationMatrix();
}
//////////////////////////////////////////////////////////////////////////
void CompositeObject::multiplyTransformationMatrix( const hlp::Matrix33f& matrix )
{
	hlp::Matrix33f newMatrix;

	for(int i = 0; i < 3; i++)
		for(int j = 0; j < 3; j++)
		{
			newMatrix.m[i][j] = 0.0f;
			for(int k = 0; k < 3; k++)
			{
				newMatrix.m[i][j] += m_transformationMatrix.m[i][k]*matrix.m[k][j];
			}
		}

	for(int i = 0; i < 3; i++)
		for(int j = 0; j < 3; j++)
			m_transformationMatrix.m[i][j] = newMatrix.m[i][j];

}
//////////////////////////////////////////////////////////////////////////
CompositeObject::~CompositeObject()
{
	for(std::list<CompositeObject*>::iterator it = m_children.begin(); it != m_children.end(); ++it)
	{
		delete (*it);
	}
	m_children.clear();
	m_namedChildren.clear();
}
//////////////////////////////////////////////////////////////////////////


